Handles `POST /v1/verifications/sessions`.
Runs the checks the tenant’s policy requires and returns the outcome. A provider outage is not an error here: it produces a review-required session, because an unreachable model says nothing about the person.
Which answer a request gets
Supplying selfie_ref or document_ref runs the session now and answers
[VerificationSessionOutcomeBody::Decided] - a decision, its reasons, and
the per-check results. Supplying neither opens a hosted capture link and
answers [VerificationSessionOutcomeBody::Opened], where nothing has been
decided and status is always AWAITING_CAPTURE; the decision arrives
later, by webhook.
Errors
Returns 401 without usable credentials, 403 when the caller may not
submit verifications, and 503 when a store the decision depends on
cannot be reached.
Authorizations
A tenant API key. Acts for exactly one tenant and cannot conclude a case, because a conclusion records a person.
Body
Request to run a verification session.
Person being verified, as the customer identifies them.
Evidence reference for the identity document image.
FIRST_TIME (the default) or REVERIFICATION.
A first-time verification is proven against the document; a reverification against the face proven when the customer first passed. Defaulting to first-time is the safe direction: it never lets a stored face stand in as identity proof by omission.
Evidence reference for the live capture.
Response
A decision when captures were supplied, or a capture link when they were not
- Option 1
- Option 2
What POST /v1/verifications/sessions answers with.
The route has two answers because it has two jobs. Supplying captures runs the session now and returns what was decided; supplying none opens a hosted capture link and returns where to send the person, with nothing decided yet. Untagged, so the body is the shape itself rather than the shape wrapped in a discriminator - which is what callers already parse.
Naming the two removes a serde_json::to_value(..).unwrap_or_default()
from each path. That turned a serialisation failure into 200 with a body
of null: a success status carrying nothing, which a caller has no way to
tell from a session that legitimately answered nothing.
Where to send the person being verified.
Contains the only copy of the capture token that will ever exist - the session keeps a hash. Treat it as a credential: send it to the person, do not log it.
When the link stops working.
Whether this is a first-time proof or a reverification.
Always AWAITING_CAPTURE: nothing has been decided yet.
Session identifier, for correlating the webhook that follows.

